/*
 * Copyright (C) 2013 Sergej Shafarenka, halfbit.de
 * Copyright 2014 Hari Krishna Dulipudi
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.zaaach.citypicker.view;


import ohos.agp.components.*;
import ohos.agp.components.element.ShapeElement;
import ohos.agp.database.DataSetSubscriber;
import ohos.agp.render.render3d.BuildConfig;
import ohos.agp.utils.Point;
import ohos.agp.utils.Rect;
import ohos.app.Context;
import ohos.multimodalinput.event.TouchEvent;


/**
 * ListView, which is capable to pin section views at its top while the rest is
 * still scrolled.
 */
public class PinnedSectionListView extends ListContainer {

    // -- inner classes

	/**
	 * List adapter to be implemented for being used with PinnedSectionListView
	 * adapter.
	 */

	public interface PinnedSectionListAdapter {
		/**
		 * This method shall return 'true' if views of given type has to be
		 * pinned.
		 *
		 * @param position  position
		 * @return boolean
		 */
		boolean isItemViewTypePinned(int position);
	}

	/** Wrapper class for pinned section view and its position in the list. */
	static class PinnedSection {
		public Component view;
		public int position;
		public long id;
	}

	// -- class fields

	// fields used for handling touch events
	private final Rect mTouchRect = new Rect();
	private final Point mTouchPoint = new Point();
	private int mTouchSlop;
	private Component mTouchTarget;
//	private MotionEvent mDownEvent;
	private TouchEvent mDownEvent;

	// fields used for drawing shadow under a pinned section
	private ShapeElement mShadowDrawable;
	private int mSectionsDistanceY;
	private int mShadowHeight;

	/** Delegating listener, can be null. */
	ScrolledListener mDelegateOnScrollListener;

	/** Shadow for being recycled, can be null. */
	PinnedSection mRecycleSection;

	/** shadow instance with a pinned view, can be null. */
	PinnedSection mPinnedSection;

	/**
	 * Pinned view Y-translation. We use it to stick pinned view to the next
	 * section.
	 */
	int mTranslateY;

	/** Default change observer. */
    private final DataSetSubscriber mDataSetObserver=new DataSetSubscriber() {
        @Override
        public void onChanged() {
//            recreatePinnedShadow();
        }

        @Override
        public void onInvalidated() {
//            recreatePinnedShadow();
        }
    };

	// -- constructors

	public PinnedSectionListView(Context context, AttrSet attrs) {
		super(context, attrs);
//		initView();

	}

	public PinnedSectionListView(Context context, AttrSet attrs, String defStyle) {
		super(context, attrs, defStyle);
//		initView();
	}




	public void PinnedSectionView(Context context, AttrSet attrSet){

	}

	/** Destroy shadow wrapper for currently pinned view */
	void destroyPinnedShadow() {
		if (mPinnedSection != null) {
			// keep shadow for being recycled later
			mRecycleSection = mPinnedSection;
			mPinnedSection = null;
		}
	}



	int findFirstVisibleSectionPosition(int firstVisibleItem, int visibleItemCount) {
		PinnedSectionListAdapter adapter = getPinnedAdapter();
		for (int childIndex = 0; childIndex < visibleItemCount; childIndex++) {
			int position = firstVisibleItem + childIndex;
			if (isItemViewTypePinned((RecycleItemProvider) adapter, position))
				return position;
		}
		return -1;
	}

	int findCurrentSectionPosition(int fromPosition) {
		PinnedSectionListAdapter adapter = getPinnedAdapter();
 		//try slow way by looking through to the next section item above
		for (int position = fromPosition; position >= 0; position--) {
			if (isItemViewTypePinned((RecycleItemProvider) adapter, position))
				return position;
		}
		return -1; // no candidate found
	}



	@Override
    public void setItemProvider(BaseItemProvider itemProvider){
        // assert adapter in debug mode
        if (BuildConfig.DEBUG && itemProvider != null) {
            if (!(itemProvider instanceof PinnedSectionListAdapter))
                throw new IllegalArgumentException("Does your itemProvider implement PinnedSectionListAdapter?");
            if (itemProvider.getComponentTypeCount() < 2)
                throw new IllegalArgumentException("Does your itemProvider handle at least two types" + " of views in getComponentTypeCount() method: items and sections?");
        }
        // unregister observer at old adapter and register on new one
		BaseItemProvider oldAdapter = getItemProvider();
        if (oldAdapter != null)
            oldAdapter.removeDataSubscriber(mDataSetObserver);
        if (itemProvider != null)
            itemProvider.addDataSubscriber(mDataSetObserver);
        // destroy pinned shadow, if new adapter is not same as old one
        if (oldAdapter != itemProvider)
            destroyPinnedShadow();

        super.setItemProvider(itemProvider);

    }




	public static boolean isItemViewTypePinned(RecycleItemProvider adapter, int position) {
		return ((PinnedSectionListAdapter) adapter).isItemViewTypePinned(position);
	}

    private PinnedSectionListAdapter getPinnedAdapter() {
        PinnedSectionListAdapter adapter;
        adapter= (PinnedSectionListAdapter) getItemProvider();
        return adapter;
    }
}